﻿using System;
using Jay.Sc2.Bof.Lib.State;

namespace Jay.Sc2.Bof.Lib.Action.Protoss
{
	public abstract class ActionProduceFromGatewayOrWarpGate : ActionProduceProtoss
	{
		private int m_CoolDownTime;
		protected ActionProduceFromGatewayOrWarpGate(int buildTime, int minerals, int gas, int food) : base(buildTime, minerals, gas, food) { m_CoolDownTime = buildTime; }

		public override int AvailableProducer(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.Gateway.AvailableForProduction + state.WarpGate.AvailableForProduction;
		}

		public abstract string EventName { get; }
		public abstract void OnProductionFinished(IBuildOrder bo);

		public override bool HaveTechnology(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.Gateway.Count + state.WarpGate.Count > 0;
		}

		public override bool IsInvalid(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.Gateway.Total + state.WarpGate.Total == 0 || base.IsInvalid(bo);
		}
		public virtual void OnProductionStarted(IBuildOrder bo) { }

		public override void Execute(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			int gateway = state.Gateway.AvailableForProduction;
			int warpgate = state.WarpGate.AvailableForProduction;
			base.Execute(bo);
			if (warpgate > 0)
			{
				// change this to reflect the real way warpgate are working (pre-production+instant warping)
				state.WarpGate.Production++;
				bo.AddAction(state.Time + 5, new ActionGeneric(EventName, (ActionGeneric.ActionExecuteDelegate)delegate(IBuildOrder ibo)
				{
					ProtossState ibostate = ibo.State as ProtossState;
					OnProductionFinished(ibo);
				}));
				bo.AddAction(state.Time + m_CoolDownTime, new ActionGeneric("ActionCooledWarpGate", (ActionGeneric.ActionExecuteDelegate)delegate(IBuildOrder ibo)
				{
					ProtossState ibostate = ibo.State as ProtossState;
					ibostate.WarpGate.Production--;
				}));
			}
			else if (gateway > 0)
			{
				state.Gateway.Production++;
				OnProductionStarted(bo);
				bo.AddAction(state.Time + BuildTime, new ActionGeneric(EventName, (ActionGeneric.ActionExecuteDelegate)delegate(IBuildOrder ibo)
				{
					ProtossState ibostate = ibo.State as ProtossState;
					ibostate.Gateway.Production--;
					OnProductionFinished(ibo);
				}));
			}
			else throw new Exception();
		}

		protected IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceGateway.Instance } };
				return m_Requirements;
			}
		}
	}

	public class ActionProduceZealot : ActionProduceFromGatewayOrWarpGate
	{
		public static ActionProduceZealot Instance = new ActionProduceZealot();
		public ActionProduceZealot() : base(38, 100, 0, 2) { }
		public override string EventName { get { return "ActionSpawnZealot"; } }
		public override void OnProductionFinished(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			state.Zealot++;
		}
	}
	public class ActionProduceStalker : ActionProduceFromGatewayOrWarpGate
	{
		public static ActionProduceStalker Instance = new ActionProduceStalker();
		public ActionProduceStalker() : base(42, 125, 50, 2) { }
		public override string EventName { get { return "ActionSpawnStalker"; } }
		public override void OnProductionFinished(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			state.Stalker++;
		}
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceCyberneticsCore.Instance, ActionHarvestGasProbe.Instance } };
				return m_Requirements;
			}
		}
		public override bool HaveTechnology(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.CyberneticsCore.Count > 0 && base.HaveTechnology(bo);
		}
		public override bool IsInvalid(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.CyberneticsCore.Total == 0 || base.IsInvalid(bo);
		}
	}
	public class ActionProduceSentry : ActionProduceFromGatewayOrWarpGate
	{
		public static ActionProduceSentry Instance = new ActionProduceSentry();
		public ActionProduceSentry() : base(42, 50, 100, 2) { }
		public override string EventName { get { return "ActionSpawnSentry"; } }
		public override void OnProductionFinished(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			state.Sentry++;
		}
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceCyberneticsCore.Instance, ActionHarvestGasProbe.Instance } };
				return m_Requirements;
			}
		}
		public override bool HaveTechnology(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.CyberneticsCore.Count > 0 && base.HaveTechnology(bo);
		}
		public override bool IsInvalid(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.CyberneticsCore.Total == 0 || base.IsInvalid(bo);
		}
	}
	public class ActionProduceHighTemplar : ActionProduceFromGatewayOrWarpGate
	{
		public static ActionProduceHighTemplar Instance = new ActionProduceHighTemplar();
		public ActionProduceHighTemplar() : base(55, 50, 150, 2) { }
		public override string EventName { get { return "ActionSpawnHighTemplar"; } }
		public override void OnProductionStarted(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			state.HighTemplarProducing++;
		}
		public override void OnProductionFinished(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			state.HighTemplarProducing--;
			state.HighTemplar++;
		}
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceTemplarArchives.Instance } };
				return m_Requirements;
			}
		}
		public override bool HaveTechnology(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.TemplarArchives.Count > 0 && base.HaveTechnology(bo);
		}
		public override bool IsInvalid(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.TemplarArchives.Total == 0 || base.IsInvalid(bo);
		}
	}
	public class ActionProduceDarkTemplar : ActionProduceFromGatewayOrWarpGate
	{
		public static ActionProduceDarkTemplar Instance = new ActionProduceDarkTemplar();
		public ActionProduceDarkTemplar() : base(55, 125, 125, 2) { }
		public override string EventName { get { return "ActionSpawnDarkTemplar"; } }
		public override void OnProductionStarted(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			state.DarkTemplarProducing++;
		}
		public override void OnProductionFinished(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			state.DarkTemplarProducing--;
			state.DarkTemplar++;
		}
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceDarkShrine.Instance } };
				return m_Requirements;
			}
		}
		public override bool HaveTechnology(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.DarkShrine.Count > 0 && base.HaveTechnology(bo);
		}
		public override bool IsInvalid(IBuildOrder bo)
		{
			ProtossState state = bo.State as ProtossState;
			return state.DarkShrine.Total == 0 || base.IsInvalid(bo);
		}
	}
}
